        TITL DAI FIRMWARE 3E859-3E9FF  V1.0  Rev.1
        ORG   :E859
*
*
*
******************************
* CHECK STATEMENT TERMINATOR *
******************************
*
* Get character from line and checks if it is
* a correct terminator (':' or car.ret).
*
* Exit: Z=1: correct terminator.
*       Z=0: incorrect.
*       BCDEHL preserved. A corrupted.
*
TSEOC   CALL  :DDD2     Get char from line, neglect
 REM tab + space
        CPI   :3A       Is it ':' ?
        RZ
        CPI   :0D       Is it 'CR' ?
        RET
*
**********************************
* CHECK IF NEXT CHARACTER IS ',' *
**********************************
*
* Exit: C updated, AF corrupted, BDEHL preserved.
*
L3E131  CALL  :E867     Check if next char is ','
        DATA  :2C
        RET
*
************************
* CHECK NEXT CHARACTER *
************************
*
* Routine finds next valid character in input. If
* it is not the character expected: syntax error.
*
* Entry: C : Points to input.
*        ASCII-value of character to compare with
*        on stack.
* Exit:  If correct: C updated, AF corrupted,
*        BDEHL preserved.
*
ECHRI   XTHL            HL pnts to expected char
        CALL  :DDD2     Get char from line, neglect
 REM tab + space
        CMP   M         Is it expected one ?
        JNZ   :DA0B     Run 'SYNTAX ERROR' if not
        INR   C         Pnts to next input
        INX   H         )
        XTHL            ) Update SP
        RET
*
*******************************
* ENCODE 'ERASE' - (not used) *
*******************************
*
* The BASIC command 'ERASE' is cancelled.
*
L3E133  LXI   D,:E678   Addr routine encode array
 REM without arguments
        JMP   :E12A     Encode
*
******************************
* INPUT FPT NUMBER INTO MACC *
******************************
*
* Entry: Z=1: Change sign too.
* Exit:  C updated, ABDEHL preserved.
*        CY=0: Error.
*
L3E134  CALL  :C01E     Input FPT number to MACC
        RNZ             Ready if Z=0
        RST   4         Else change sign MACC
        DATA  :1B
        RET
*
*******************************
* STORE QUOTED TEXT INTO EBUF *
*******************************
*
* Entry: C points to 1st '"'.
*
L3E135  INR   C
        JMP   :E69C     Store text in EBUF
*
********************************
* STORE A HEX NUMBER INTO EBUF *
********************************
*
* Entry: C points to '#' of hex number.
*
EHEX    INR   C
        JMP   :E590     Hex nr into EBUF
*
**********************************
* ENCODE AN INT NUMBER INTO EBUF *
**********************************
*
L3E137  CALL  :E8AF     #14 into EBUF
        CPI   :23       '#' ?
        JZ    :E899     Then jump
        CALL  :E57B     INT nr into EBUF
L3E139  JNC   :E8B7     Evt run 'SYNTAX ERROR'
        JMP   :E15C     Quit
 REM
* If hex number:
 REM
L3E138  CALL  :E884     Hex nr into EBUF
        JMP   :E893
*
        DATA  :FF
        DATA  :FF
        DATA  :FF
*
*****************
* ENCODE 'DATA' *
*****************
*
EDATA   MOV   A,L
        CPI   :42
        JNZ   :DA0B     Run 'SYNTAX ERROR' if not
        JMP   :E366     Encode text
*
********************************
* part of END ENCODING (3E6B5) *
********************************
*
L3E140  INR   E
        JMP   :E6C8
*
*********************************
* CODE FOR INT NUMBER INTO EBUF *
*********************************
*
* Gets also next character to encode.
*
L3E141  MVI   M,:14     INT code (#14) in EBUF
        CALL  :E018     Update EBUF pointer
        JMP   :DDD2     Get char from line, neglect
 REM tab + space
*
*************************************************
* ERROR EXIT OF ENCODE INT NR INTO EBUF (3E888) *
*************************************************
*
L3E142  LHLD  :0132     Get EFEPT
        LXI   D,:FFFC
        DAD   D         Set back linepntr
        SHLD  :0100     Store start current line
        JMP   :DA0B     Run 'SYNTAX ERROR'
*
        DATA  :FF
*
**************************************
* ASCII TABLE UPPER CASE (UNSHIFTED) *
**************************************
*
KEYTU   DATA  :30       0
        DATA  :31       1
        DATA  :32       2
        DATA  :33       3
        DATA  :34       4
        DATA  :35       5
        DATA  :36       6
        DATA  :37       7
        DATA  :38       8
        DATA  :39       9
        DATA  :3A       :
        DATA  :3B       ;
        DATA  :2C       ,
        DATA  :2D       -
        DATA  :2E       .
        DATA  :2F       /
        DATA  :0D       car ret
        DATA  :41       A
        DATA  :42       B
        DATA  :43       C
        DATA  :44       D
        DATA  :45       E
        DATA  :46       F
        DATA  :47       G
        DATA  :48       H
        DATA  :49       I
        DATA  :4A       J
        DATA  :4B       K
        DATA  :4C       L
        DATA  :4D       M
        DATA  :4E       N
        DATA  :4F       O
        DATA  :50       P
        DATA  :51       Q
        DATA  :52       R
        DATA  :53       S
        DATA  :54       T
        DATA  :55       U
        DATA  :56       V
        DATA  :57       W
        DATA  :58       X
        DATA  :59       Y
        DATA  :5A       Z
        DATA  :5B       [
        DATA  :5E       ^
        DATA  :20       space
        DATA  :00       (rept)
        DATA  :08       char del
        DATA  :10       cursor up
        DATA  :11       cursor down
        DATA  :12       cursor left
        DATA  :13       cursor right
        DATA  :09       tab
        DATA  :80       ctrl
        DATA  :00       (break)
        DATA  :00       (shift)
*
************************************
* ASCII TABLE LOWER CASE (SHIFTED) *
************************************
*
KEYTS   DATA  :30       0
        DATA  :21       !
        DATA  :22       "
        DATA  :23       #
        DATA  :24       $
        DATA  :25       %
        DATA  :26       &
        DATA  :27       '
        DATA  :28       (
        DATA  :29       )
        DATA  :2A       *
        DATA  :2B       +
        DATA  :3C       <
        DATA  :3D       =
        DATA  :3E       >
        DATA  :3F       ?
        DATA  :0D       car ret
        DATA  :61       a
        DATA  :62       b
        DATA  :63       c
        DATA  :64       d
        DATA  :65       e
        DATA  :66       f
        DATA  :67       g
        DATA  :68       h
        DATA  :69       i
        DATA  :6A       j
        DATA  :6B       k
        DATA  :6C       l
        DATA  :6D       m
        DATA  :6E       n
        DATA  :6F       o
        DATA  :70       p
        DATA  :71       q
        DATA  :72       r
        DATA  :73       s
        DATA  :74       t
        DATA  :75       u
        DATA  :76       v
        DATA  :77       w
        DATA  :78       x
        DATA  :79       y
        DATA  :7A       z
        DATA  :5D       ]
        DATA  :7E       ~
        DATA  :20       space
        DATA  :00       (rept)
        DATA  :08       char del
        DATA  :14       window up
        DATA  :15       window down
        DATA  :16       window left
        DATA  :17       window right
        DATA  :09       tab
        DATA  :80       ctrl
        DATA  :00       (break)
        DATA  :00       (shift)
*
************************************
* GET INPUTS FROM KEYBOARD OR DINC *
************************************
*
* Part of RESET (C719). Determines input source
* depending on 1st input done.
*
L3E143  CALL  :D6BB     Scan keyb; char in A
        RC              Ready if break pressed
        RNZ             Ready if key input done
        JMP   :EFF4     Else: Get input from DINC
*
        DATA  :FF
        DATA  :FF
*
**********************************************
* LOAD ASCII VALUE FOR KEY PRESSED IN BUFFER *
**********************************************
*
* From the key pressed, the offset to the start-
* address of the ASCII table is calculated. The
* ASCII value for the pressed key is stored in
* the circular buffer KLIND.
*
* Entry: B : Column number.
*        C : Row number.
* Exit:  All registers preserved.
*
INKEY   PUSH  PSW
        PUSH  B
        PUSH  H
        MVI   A,:07     )
        SUB   B         )
        ADD   A         ) Calc offset of startaddr
        ADD   A         ) for key pressed.
        ADD   A         )   Store it in C
        ADD   C         )
        MOV   C,A       )
        LHLD  :02A7     Get startaddr ASCII table
        MVI   B,:00
        CPI   :11       )
        JC    :E95D     ) Check if key is a char
        CPI   :2B       ) A-Z
        JNC   :E95D     )
        LDA   :02C3     Get shift lock value
        MOV   B,A       in B
L3E145  LDA   :02B0     Get 'shift' byte
        XRA   B         Take CTRL into account
        ANI   :40       A=#40 if shift, 00 when not
        JZ    :E96C     Jump if no shift
        PUSH  D
        LXI   D,:0038   Add. offset for lower case
 REM table
        DAD   D         Startaddr lower case table
 REM now in HL
        POP   D
L3E146  MVI   B,:00
        DAD   B         Add offset to startaddr
        MOV   A,M       Get ASCII value from table
        ORA   A         Check if Break, Rept, Shift
        JZ    :E98E     Then Pop, ret
        CPI   :80       Check if CTRL
        JZ    :E992     Then update CTRL flag
        MOV   B,A       Store ASCII value in B
        LHLD  :02BE     Get addr next pos in KLIND
        PUSH  H         Store KLIIN on stack
        CALL  :D69C     Update KLIND pointer
        LDA   :02C0     Get lsbyte next output pos
 REM of KLIND
        CMP   L         Compare with KLIIN
        JZ    :E98D     Abort if buffer full
        SHLD  :02BE     Update KLIIN
        XTHL            Get old KLIIN from stack
        MOV   M,B       Store ASCII char in KLIND
L3E147  POP   H
L3E148  POP   H
        POP   B
        POP   PSW
        RET
 REM
* Update CTRL flag:
 REM
L3E149  LDA   :02C3     Get shiftlock value
        CMA             Invert it
        STA   :02C3     And store it again
        JMP   :E98E     Pop, ret
*
****************
* HEAP REQUEST *
****************
*
* The routine checks the heap for free areas. Evt.
* consecutive free areas are consolidated. If this
* procedure finds a free area min. 2 bytes larger
* than requested, then it is reserved by setting
* the length bytes (msb=0). An evt. resting free
* area is set with length bytes and msb=1 (this
* area must be >= 2 bytes).
* The heap contents is never moved to obtain one
* large consolidated area of free bytes!!
*
* Entry: DE: Length requested heap space.
* Exit:  AFBCDE preserved.
*        HL: Points to a 2-byte length of the re-
*            quested gap. If no space available,
*            it points to an error routine.
*
HREQ    PUSH  PSW
        PUSH  B
        PUSH  D
        MOV   B,D       ) Reqd length in BC
        MOV   C,E       )
        LHLD  :029B     Get startaddr Heap
HRQ10   MOV   D,M       )
        INX   H         ) Contents 1st 2 bytes of
        MOV   E,M       ) Heap in DE (length)
        INX   H         )
        MOV   A,D       1st byte in A
        ANI   :7F       Mask bit 'free/used'
        CMP   D
        MOV   D,A       D is length without msb
        JZ    :D227     If area not free: check if
 REM end of heap reached. JMP
 REM #E9FA if not
 REM
* If free area found: Check all next heap entries
* and accumulate all free areas in succession:
 REM
HRQ20   PUSH  H         Save startaddr area +2
        DAD   D         Begin next area in HL
        MOV   A,M
        ORA   A         Check msb of this area
        JP    :E9C7     Jump if area occupied
        INX   H
        MOV   A,E
        ADD   M         Add lobyte length next area
 REM length previous area
        MOV   E,A
        MOV   A,D
        DCX   H
        ADC   M         Add hibyte length next area
 REM length previous area
        ANI   :7F       Skip bit 'free/occupied'
        MOV   D,A
        INX   D
        INX   D         Add 2 extra bytes
        POP   H         Restore start free area +2
        JMP   :E9B0     Check next area
 REM
* Next area is not free:
 REM
HRQ30   POP   H         Restore start free area +2
        PUSH  H
        DCX   H
        MOV   M,E       )
        DCX   H         ) Store total free length in
        MOV   A,D       ) 1st 2 bytes of free area
        ORI   :80       )
        MOV   M,A       )
 REM Space available here: HL pnt
 REM to start free area +2; DE is
 REM size free area; BC size reqd
        MOV   A,E       )
        SUB   C         )
        MOV   L,A       ) Calc free length - reqd.
        MOV   A,D       ) length; result in HL
        SBB   B         )
        MOV   H,A       )
        JM    :E9F9     Space not sufficient: Leave
 REM consolidated area as free
        JNZ   :E9E4     Jump if sufficient space
        ORA   L
        JZ    :E9F0     Jump if just enough
        DCR   A
        JZ    :E9F9     Not useable if 1 free byte
 REM left
 REM
* Set not used part of free area to free:
 REM
HRQ40   XCHG            Addr free area in DE
        DCX   D
        DCX   D         Reserve 2 bytes for length
        POP   H         Restore start free area +2
        PUSH  H
        DAD   B         Add reqd length to find
 REM start of resting free area
        MOV   A,D
        ORI   :80       Set free flag
        MOV   M,A       )
        INX   H         ) Length free area into heap
        MOV   M,E       )
 REM
* Reserve area for requested entry:
 REM
HRQ50   POP   H         Restore start free area +2
        DCX   H
        MOV   M,C       )
        DCX   H         ) Reqd length in 1st 2 bytes
        MOV   M,B       )
        POP   D
        POP   B
        POP   PSW
        RET
 REM
* Area too small:
 REM
HRQ70   POP   H         Restore start free area
HRQ75   DAD   D         HL pnts to next area
        JMP   :E9A4     Check next area
 REM
        DATA  :FF
        DATA  :FF
*
*
*
*
        END
